package naito_rescue.router;

import rescuecore2.misc.*;
import rescuecore2.misc.geometry.*;
import rescuecore2.worldmodel.*;
import rescuecore2.standard.entities.*;

import naito_rescue.*;
import naito_rescue.agent.*;
import naito_rescue.router.object.*;
import naito_rescue.object.*;
import java.util.*;

import static naito_rescue.debug.DebugUtil.*;

public final class NAITORouter{
	private StandardWorldModel model;
	private NAITOAgent         owner;
	private MyLogger           logger;
	private ConnectivityGraph  graph;
	private AStarModule        astarModule;
	private BackwardAStarModule backAstarModule;
	private SimpleSearchModule simpleModule;
	private AllPathsFindModule allFindModule;
	private AdaptiveAStarModule aastarModule;
	
	private PassableChecker checker;
	
    public NAITORouter(NAITOAgent owner) {
		this.owner = owner;
		this.model = owner.getWorldModel();
		this.logger = this.owner.getLogger();
		
		//OPEN = new ArrayList<Area>();
		//CLOSED = new ArrayList<Area>();
		//estimates = new HashMap<Area, Integer>();
		//ancestors = new HashMap<Area, Area>();
		
		checker = new PassableChecker(owner);
		this.graph = new ConnectivityGraph(owner.getWorldModel());
		this.simpleModule = new SimpleSearchModule(owner, graph);
		this.astarModule = new AStarModule(owner, graph);
		this.backAstarModule = new BackwardAStarModule(owner, graph);
		this.allFindModule = new AllPathsFindModule(owner, graph);
		this.aastarModule = new AdaptiveAStarModule(owner, graph);
	}
	/**
	*
	*  幅優先探索
	*
	*/
    public List<EntityID> breadthFirstSearch(EntityID... goals) {
        return simpleModule.search(owner.getLocation().getID(), Arrays.asList(goals));
    }
    public List<EntityID> breadthFirstSearch(Collection<? extends StandardEntity> entities){
    	List<EntityID> ids = new ArrayList<EntityID>();
    	for(StandardEntity entity : entities){
			ids.add(entity.getID());
		}
		return simpleModule.search(owner.getLocation().getID(), ids);
    }
    public List<EntityID> breadthFirstSearch(StandardEntity... entities){
    	return breadthFirstSearch(Arrays.asList(entities));
    }
	/**
	*
	*  A*探索
	*
	*/
    public List<EntityID> astarSearch(EntityID... goals){
    	return this.astarModule.search(owner.getLocation().getID(), Arrays.asList(goals));
    }
    public List<EntityID> astarSearch(StandardEntity goal){
    	return this.astarModule.search(owner.getLocation().getID(), Arrays.asList(goal.getID()));
    }
    public List<EntityID> backwardAStarSearch(EntityID... goals){
    	return this.backAstarModule.search(owner.getLocation().getID(), Arrays.asList(goals));
    }
    public List<EntityID> backwardAStarSearch(Collection<EntityID> goals){
    	return this.backAstarModule.search(owner.getLocation().getID(), goals);
    }
    public List<EntityID> backwardAStarSearch(StandardEntity goal){
    	return backwardAStarSearch(goal.getID());
    }
    public List<EntityID> astarSearch2(EntityID... goals){
    	return this.astarModule.search2(owner.getLocation().getID(), Arrays.asList(goals));
    }
    public List<EntityID> astarSearch2(StandardEntity goal){
    	return this.astarModule.search2(owner.getLocation().getID(), Arrays.asList(goal.getID()));
    }
    /*
    public List<EntityID> backwardAStarSearch2(EntityID... goals){
    	return this.backAstarModule.search2(owner.getLocation().getID(), Arrays.asList(goals));
    }
    public List<EntityID> backwardAStarSearch2(StandardEntity goal){
    	return backwardAStarSearch2(goal.getID());
    }
    */
    
    /**
    *
    * Adaptive A* 探索
    *
    */
    public List<EntityID> adaptiveAStarSearch(EntityID goal){
    	return this.aastarModule.search(owner.getLocation().getID(), goal);
    }
    public List<EntityID> adaptiveAStarSearch(StandardEntity goal){
    	return this.aastarModule.search(owner.getLocation().getID(), goal.getID());
    }

    /**
    *
    *  通常探索用インタフェース
    *
    */
    public List<EntityID> getRoute(EntityID... goals){
    	return this.backAstarModule.search(owner.getLocation().getID(), Arrays.asList(goals));
    }
    public List<EntityID> getRoute(StandardEntity goal){
    	return getRoute(goal.getID());
    }
    /**
    *
    * すべての解候補を探索する
    * 不用意に呼ぶとエラいことになりますよ(計算量が...)
    *
    */
    public List<List<EntityID>> searchAllPaths(EntityID goal){
    	List<List<EntityID>> lists = new ArrayList<List<EntityID>>();
    	allFindModule.search(goal, lists);
    	return lists;
    }
    /**
    *
    *  その他ユーティリティメソッド等
    *
    */
	public Set<EntityID> getNeighbors(EntityID id){
		return this.graph.getNeighbors(id);
	}
	public int computePathLength(List<EntityID> path){
		return astarModule.computePathLength(path);
	}
	public PassableChecker getPassableChecker(){
		return this.checker;
	}
}
